package com.biz.primus.common.utils;

import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import org.springframework.core.ResolvableType;
import org.springframework.core.convert.converter.Converter;
import org.springframework.util.Assert;

/**
 * guava风格的属性复制器,提供属性类型转换的功能
 * @author yanweijin
 * @date 2017/9/19
 */
public class Copier {

	private final Object source;

	private Table<Class,Class,Converter> converterTable = HashBasedTable.create();

	private boolean ignoreNullValue = false;

	private String[] ignoreProperties = new String[]{};

	private Copier(Object source){
		this.source = source;
	}

	public static Copier from(Object source){
		return new Copier(source);
	}

	/**
	 * 注册属性转换器,可以多次调用
	 * @param converter spring提供的转换器接口
	 * @return
	 */
	public <S,T> Copier usePropertyConverter(Converter<S,T> converter){
		Assert.notNull(converter,"属性转换器不能为空");
		ResolvableType resolvableType = ResolvableType.forInstance(converter);
		ResolvableType[] generics = resolvableType.getGenerics();
		Assert.isTrue(generics.length==2,"converter的泛型数量必须为2");
		converterTable.put(generics[0].getRawClass(),generics[1].getRawClass(),converter);
		return this;
	}


	/**
	 * 忽略null值,source对象中的null值不会写入target
	 * @return
	 */
	public Copier ignoreNullValue(){
		this.ignoreNullValue = true;
		return this;
	}

	/**
	 * 注册要忽略的属性名称,这些属性不会被写入target
	 * @param propertyNames
	 * @return
	 */
	public Copier ignoreProperties(String...propertyNames){
		this.ignoreProperties = propertyNames;
		return this;
	}

	public <T> T to(T target){
		Assert.notNull(target,"target不能为null");
		return CopyUtils.copyProperties(source,target,ignoreNullValue,converterTable,ignoreProperties);
	}
//
//	@Data
//	@AllArgsConstructor
//	static class Student{
//		String name;
//		int age;
//		String id;
//	}
//
//	@Getter
//	@Setter
//	static class Person{
//		String name;
//		int age;
//		Long id;
//	}
//
//
//	public static void main(String[] args) {
//		Student student = new Student("zhangsan",15,"12345");
//
//		Person person = Copier.from(student).to(new Person());
//
//		System.out.println(person);
//
//	}
//


}
